using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using GamePlay.Features.Shared;
using GamePlay.Framework.Events;
using UnityEngine;
using NativeWebSocket;
using UnityEngine.Networking;

namespace GamePlay.Framework.Network
{
    /// <summary>
    /// WebSocket客户端微信平台实现 - 使用NativeWebSocket库
    /// </summary>
    public class WebSocketClientWX : MonoBehaviour
    {
        #region 单例实现

        private static WebSocketClientWX _instance;

        public static WebSocketClientWX Instance
        {
            get
            {
                if (_instance == null)
                {
                    GameObject obj = new GameObject("WebSocketClientWX");
                    _instance = obj.AddComponent<WebSocketClientWX>();
                    DontDestroyOnLoad(obj);
                }
                return _instance;
            }
        }

        private void Awake()
        {
            if (_instance != null && _instance != this)
            {
                Destroy(gameObject);
                return;
            }

            _instance = this;
            DontDestroyOnLoad(gameObject);

            // 初始化消息队列和缓存
            _messageQueue = new Queue<WebSocketMessage>();
            _sendBuffer = new List<byte>(1024 * 64); // 64KB初始缓冲区

            // 设置初始重连参数
            _maxReconnectAttempts = 5;
            //_reconnectAttempts = _maxReconnectAttempts;

            // 注册事件
            OnConnected += () => Emit(new ConnectServerArgs());
            OnDisconnected += (_, __) => Emit(new DisconnectServerArgs());
        }

        #endregion

        #region 事件和委托

        public event Action OnConnected;
        public event Action<int, string> OnDisconnected;
        public event Action<string> OnError;
        public event Action<string> OnTextMessageReceived;
        public event Action<byte[]> OnBinaryMessageReceived;
        public event Action<int, int> OnReconnectAttempt; // 当前尝试，最大尝试
        public event Action<ConnectionStatus> OnConnectionStatusChanged; // 新增：连接状态变化事件

        #endregion

        #region 字段和属性

        private WebSocket _webSocket;
        private string _serverUrl = "ws://aichunchun.xyz:8888/ws";
        private bool _isConnected = false;
        public bool IsConnected => _isConnected && _connectionState == ConnectionState.Connected;

        private enum ConnectionState { Disconnected, Connecting, Connected, Disconnecting }
        private ConnectionState _connectionState = ConnectionState.Disconnected;

        // 连接状态枚举
        public enum ConnectionStatus
        {
            Disconnected,
            Connecting,
            Connected,
            ConnectionFailed,
            ServerUnreachable,
            Timeout,
            Error
        }

        // 当前连接状态
        private ConnectionStatus _connectionStatus = ConnectionStatus.Disconnected;
        public ConnectionStatus CurrentConnectionStatus => _connectionStatus;

        // 重连设置
        private bool _reconnectOnDisconnect = true;
        private int _reconnectAttempts = 0;
        private int _maxReconnectAttempts = 5;
        private float _reconnectDelay = 3f;
        private float _reconnectTimer = 0f;

        // 消息处理
        private Queue<WebSocketMessage> _messageQueue = new Queue<WebSocketMessage>();
        private List<byte> _sendBuffer = new List<byte>(1024 * 64); // 64KB初始缓冲区

        [SerializeField] private bool _debugMode = true;
        public string ServerUrl => _serverUrl;

        private Action<bool> _onConnectCallback;
        private Action _onDisconnectCallback;

        // 连接超时设置
        private float _connectionTimeout = 10f;
        private string _lastErrorMessage = string.Empty;
        public string LastErrorMessage => _lastErrorMessage;

        #endregion

        #region Unity生命周期

        private void Update()
        {
#if !UNITY_WEBGL || UNITY_EDITOR
            if (_webSocket != null)
            {
                _webSocket.DispatchMessageQueue();
            }
#endif

            if (_messageQueue != null)
            {
                ProcessMessageQueue();
            }
            else
            {
                // 如果队列为空，则初始化
                _messageQueue = new Queue<WebSocketMessage>();
                LogError("WebSocket消息队列未初始化");
            }

            HandleReconnection();
        }

        private async void OnApplicationQuit()
        {
            await DisconnectAsync();
        }

        #endregion

        #region 公共API

        /// <summary>
        /// 连接到WebSocket服务器
        /// </summary>
        public void ConnectAsync(string url = null, Action<bool> callback = null)
        {
            // 保存URL和回调
            _serverUrl = url ?? _serverUrl;
            _onConnectCallback = callback;

            // 重置错误消息
            _lastErrorMessage = string.Empty;

            // 如果正在连接或已连接，直接返回
            if (_connectionState == ConnectionState.Connecting)
            {
                SetConnectionStatus(ConnectionStatus.Connecting, "已经在连接过程中");
                callback?.Invoke(false);
                return;
            }

            if (_connectionState == ConnectionState.Connected && _isConnected && _webSocket != null && _webSocket.State == WebSocketState.Open)
            {
                SetConnectionStatus(ConnectionStatus.Connected, "已连接到服务器");
                callback?.Invoke(true);
                return;
            }

            // 设置初始重连尝试次数
            if (_reconnectOnDisconnect)
            {
                Log($"【重连管理】初始化重连次数: {_maxReconnectAttempts}");
                _reconnectAttempts = _maxReconnectAttempts;
            }

            // 启动连接协程
            StartCoroutine(ConnectCoroutine());
        }

        /// <summary>
        /// 断开WebSocket连接
        /// </summary>
        public async Task<bool> DisconnectAsync(Action callback = null)
        {
            _onDisconnectCallback = callback;

            // 如果已经断开连接，直接返回
            if (_webSocket == null || _connectionState == ConnectionState.Disconnected)
            {
                _onDisconnectCallback?.Invoke();
                _onDisconnectCallback = null;
                return true;
            }

            // 设置状态为正在断开
            SetConnectionState(ConnectionState.Disconnecting);
            SetConnectionStatus(ConnectionStatus.Disconnected, "正在断开连接...");

            // 保存临时变量，捕获当前的回调
            var disconnectCallback = _onDisconnectCallback;
            _onDisconnectCallback = null;

            try
            {
                // 只有在连接状态为Open时才关闭
                if (_webSocket.State == WebSocketState.Open)
                {
                    await _webSocket.Close();
                }

                // 清理资源
                _isConnected = false;
                SetConnectionState(ConnectionState.Disconnected);
                SetConnectionStatus(ConnectionStatus.Disconnected, "已断开连接");

                // 执行回调
                disconnectCallback?.Invoke();
                return true;
            }
            catch (Exception ex)
            {
                LogError($"断开连接失败: {ex.Message}");

                // 即使失败也设置为断开状态
                _isConnected = false;
                SetConnectionState(ConnectionState.Disconnected);
                SetConnectionStatus(ConnectionStatus.Disconnected, "断开连接失败");

                // 执行回调
                disconnectCallback?.Invoke();
                return false;
            }
        }

        /// <summary>
        /// 发送文本消息
        /// </summary>
        public async Task<bool> SendTextAsync(string message)
        {
            if (!IsConnectedAndReady())
            {
                LogError($"无法发送消息：未连接到服务器或连接状态异常 (状态: {_connectionState}, 已连接: {_isConnected})");
                return false;
            }

            try
            {
                await _webSocket.SendText(message);
                if (_debugMode) Log($"已发送: {message}");
                return true;
            }
            catch (Exception ex)
            {
                LogError($"发送文本失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 发送二进制消息
        /// </summary>
        public async Task<bool> SendBinaryAsync(byte[] data)
        {
            if (!IsConnectedAndReady())
            {
                LogError($"无法发送二进制数据：未连接到服务器或连接状态异常 (状态: {_connectionState}, 已连接: {_isConnected})");
                return false;
            }

            if (data == null || data.Length == 0)
            {
                LogError("无法发送空的二进制数据");
                return false;
            }

            // 记录消息大小
            Log($"[消息大小] 准备发送二进制数据: {data.Length}字节");

            // 如果消息大于0.5MB，记录更详细的信息
            if (data.Length > 512 * 1024)
            {
                Log($"[警告] 正在发送较大的消息: {data.Length}字节 ({data.Length / 1024.0f:F2}KB)");

                // 解析消息头以获取更多信息
                if (data.Length >= 8)
                {
                    int messageLength = BitConverter.ToInt32(data, 0);
                    int messageId = BitConverter.ToInt32(data, 4);
                    Log($"[消息分析] 消息ID={messageId}, 消息头中记录的消息长度={messageLength}字节");

                    // 检查长度是否一致
                    if (messageLength != data.Length - 8)
                    {
                        LogError($"[消息分析] 警告: 消息头部长度字段({messageLength})与实际数据长度({data.Length - 8})不匹配");
                    }
                }
            }

            // 验证消息大小是否超出限制
            const int maxMessageSize = 1048576; // 1MB (1048576字节)
            if (data.Length > maxMessageSize)
            {
                LogError($"发送消息过大: {data.Length}字节，超出最大限制{maxMessageSize}字节");
                return false;
            }

            try
            {
                await _webSocket.Send(data);
                if (_debugMode) Log($"已发送二进制数据: {data.Length} 字节");
                return true;
            }
            catch (Exception ex)
            {
                LogError($"发送二进制数据失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 检查连接是否处于就绪状态
        /// </summary>
        public bool IsConnectedAndReady()
        {
            return _isConnected && _connectionState == ConnectionState.Connected &&
                   _webSocket != null && _webSocket.State == WebSocketState.Open;
        }

        /// <summary>
        /// 设置重连配置
        /// </summary>
        public void SetReconnectConfig(bool enabled, int maxAttempts = 5, float delay = 3f)
        {
            _reconnectOnDisconnect = enabled;
            _maxReconnectAttempts = maxAttempts;
            _reconnectDelay = delay;

            // 只有当启用重连且当前未连接时才设置尝试次数
            if (enabled && _connectionState == ConnectionState.Disconnected)
            {
                _reconnectAttempts = maxAttempts;
            }
            else if (!enabled)
            {
                _reconnectAttempts = 0;
            }

            if (_debugMode) Log($"重连配置: {(enabled ? "已启用" : "已禁用")}, 尝试次数:{maxAttempts}, 延迟:{delay}秒");
        }

        /// <summary>
        /// 设置连接超时时间
        /// </summary>
        public void SetConnectionTimeout(float timeoutSeconds)
        {
            _connectionTimeout = Mathf.Max(3f, timeoutSeconds);
            Log($"连接超时时间设置为: {_connectionTimeout}秒");
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 连接协程
        /// </summary>
        private IEnumerator ConnectCoroutine()
        {
            SetConnectionState(ConnectionState.Connecting);
            SetConnectionStatus(ConnectionStatus.Connecting, "正在连接到服务器...");

            Log($"准备连接到WebSocket服务器: {_serverUrl}");

            // 创建WebSocket对象
            WebSocket webSocket = null;

            try
            {
                Log("创建WebSocket连接对象...");

                // 创建NativeWebSocket对象
                webSocket = new WebSocket(_serverUrl);

                Log($"WebSocket对象创建成功，准备连接到: {_serverUrl}");
            }
            catch (Exception ex)
            {
                _lastErrorMessage = $"创建WebSocket连接失败: {ex.Message}";
                LogError(_lastErrorMessage);
                SetConnectionState(ConnectionState.Disconnected);
                SetConnectionStatus(ConnectionStatus.Error, _lastErrorMessage);
                _onConnectCallback?.Invoke(false);
                yield break;
            }

            // 保存WebSocket实例
            _webSocket = webSocket;

            // 注册事件处理程序
            Log("注册WebSocket事件处理程序...");
            _webSocket.OnOpen += OnWebSocketOpenHandler;
            _webSocket.OnClose += OnWebSocketCloseHandler;
            _webSocket.OnError += OnWebSocketErrorHandler;
            _webSocket.OnMessage += OnWebSocketMessageHandler;

            // 连接超时计时器
            float elapsed = 0f;
            bool connectCalled = false;
            bool connectionComplete = false;

            // 尝试连接
            try
            {
                Log($"正在启动WebSocket连接: {_serverUrl}...");

                // 启动连接，但不等待它完成
                var connectTask = _webSocket.Connect();
                connectCalled = true;

                Log("WebSocket连接请求已发送，等待服务器响应...");
            }
            catch (Exception ex)
            {
                _lastErrorMessage = $"启动WebSocket连接失败: {ex.Message}";
                LogError(_lastErrorMessage);
                SetConnectionState(ConnectionState.Disconnected);
                SetConnectionStatus(ConnectionStatus.Error, _lastErrorMessage);
                _onConnectCallback?.Invoke(false);
                UnregisterWebSocketEvents();
                yield break;
            }

            // 只有在连接成功启动后才等待
            if (connectCalled)
            {
                Log($"等待WebSocket连接完成，超时时间: {_connectionTimeout}秒");

                // 记录开始等待的时间
                float startTime = Time.time;

                // 等待连接完成或超时
                while (!connectionComplete && _connectionState == ConnectionState.Connecting && elapsed < _connectionTimeout)
                {
                    elapsed = Time.time - startTime;

                    // 检查连接状态
                    if (_webSocket.State == WebSocketState.Open)
                    {
                        connectionComplete = true;
                        break;
                    }
                    else if (_webSocket.State == WebSocketState.Closed || _webSocket.State == WebSocketState.Closing)
                    {
                        _lastErrorMessage = "WebSocket连接被关闭";
                        LogError(_lastErrorMessage);
                        SetConnectionState(ConnectionState.Disconnected);
                        SetConnectionStatus(ConnectionStatus.ConnectionFailed, _lastErrorMessage);
                        _onConnectCallback?.Invoke(false);
                        UnregisterWebSocketEvents();
                        yield break;
                    }

                    // 每隔2秒记录一次等待时间
                    if (Mathf.FloorToInt(elapsed) % 2 == 0 && Mathf.FloorToInt(elapsed) > 0 && Mathf.FloorToInt(elapsed) == elapsed)
                    {
                        Log($"WebSocket连接等待中... {elapsed:F1}/{_connectionTimeout}秒");
                    }

                    yield return null;
                }

                // 检查是否超时
                if (!connectionComplete && _connectionState == ConnectionState.Connecting)
                {
                    _lastErrorMessage = $"WebSocket连接超时({_connectionTimeout}秒)，服务器可能未启动或不可达: {_serverUrl}";
                    LogError(_lastErrorMessage);
                    SetConnectionState(ConnectionState.Disconnected);
                    SetConnectionStatus(ConnectionStatus.Timeout, _lastErrorMessage);
                    _onConnectCallback?.Invoke(false);

                    // 尝试关闭连接
                    try
                    {
                        Log("连接超时，正在清理WebSocket连接...");
                        var closeTask = _webSocket.Close();
                    }
                    catch (Exception ex)
                    {
                        LogError($"关闭超时连接失败: {ex.Message}");
                    }

                    UnregisterWebSocketEvents();

                    // 提供更多故障排除信息
                    LogError("WebSocket连接故障排除提示:");
                    LogError("1. 确认服务器是否已启动并正在运行");
                    LogError("2. 检查URL是否正确 (ws://服务器IP:端口/路径)");
                    LogError("3. 确认端口是否已开放并且没有被防火墙阻止");
                    LogError("4. 检查网络连接是否稳定");
                    LogError($"5. 当前连接URL: {_serverUrl}");
                }
                else if (_connectionState == ConnectionState.Connected)
                {
                    Log($"WebSocket连接成功建立，用时: {elapsed:F1}秒");
                }
                else
                {
                    Log($"WebSocket连接过程中状态变为: {_connectionState}，可能由于错误或手动中断");
                }
            }
        }

        /// <summary>
        /// 处理消息队列
        /// </summary>
        private void ProcessMessageQueue()
        {
            // 确保队列已初始化
            if (_messageQueue == null)
            {
                _messageQueue = new Queue<WebSocketMessage>();
                LogError("消息队列未初始化，已重新创建");
                return;
            }

            // 处理消息队列
            int maxMessagesPerFrame = 10;
            int processedCount = 0;

            while (_messageQueue.Count > 0 && processedCount < maxMessagesPerFrame)
            {
                var message = _messageQueue.Dequeue();
                processedCount++;

                try
                {
                    // 只处理二进制消息，不处理文本消息，避免重复处理
                    // NativeWebSocket库已经直接在OnWebSocketMessageHandler中调用了OnBinaryMessageReceived
                    // 此处不再需要额外处理

                    // 如果需要其他类型消息处理，可以在此添加其他处理逻辑
                }
                catch (Exception ex)
                {
                    LogError($"处理消息时出错: {ex.Message}");
                }
            }
        }

        /// <summary>
        /// 处理重连逻辑
        /// </summary>
        private void HandleReconnection()
        {
            // 只有在断开连接状态且启用了重连才处理
            if (_connectionState != ConnectionState.Disconnected || !_reconnectOnDisconnect || _reconnectAttempts <= 0)
                return;

            // 更新重连计时器
            _reconnectTimer += Time.deltaTime;

            // 检查是否达到重连延迟时间
            if (_reconnectTimer >= _reconnectDelay)
            {
                _reconnectTimer = 0f;

                // 当前尝试的次数（从第1次开始计数）
                int currentAttempt = _maxReconnectAttempts - _reconnectAttempts + 1;

                if (_debugMode) Log($"尝试重连 #{currentAttempt}/{_maxReconnectAttempts}");

                // 触发重连尝试事件
                OnReconnectAttempt?.Invoke(currentAttempt, _maxReconnectAttempts);

                // 尝试重新连接
                ConnectAsync(_serverUrl, success =>
                {
                    if (success)
                    {
                        Log($"【重连管理】重连成功，重置重连次数: 0");
                        _reconnectAttempts = 0;
                    }
                    else
                    {
                        _reconnectAttempts--;
                        LogError($"【重连管理】重连失败，剩余重连次数: {_reconnectAttempts}");

                        if (_reconnectAttempts <= 0)
                        {
                            LogError($"【重连管理】已达到最大重连次数 ({_maxReconnectAttempts})，停止重连");
                            _reconnectOnDisconnect = false;
                        }
                    }
                });
            }
        }

        /// <summary>
        /// 设置连接状态
        /// </summary>
        private void SetConnectionState(ConnectionState state)
        {
            _connectionState = state;
            if (_debugMode) Log($"连接状态: {state}");
        }

        /// <summary>
        /// 设置连接状态并触发事件
        /// </summary>
        private void SetConnectionStatus(ConnectionStatus status, string message = "")
        {
            if (_connectionStatus != status)
            {
                _connectionStatus = status;
                if (_debugMode) Log($"连接状态变更: {status} - {message}");

                // 触发状态变化事件
                OnConnectionStatusChanged?.Invoke(status);

                // 更新错误消息
                if (status == ConnectionStatus.Error ||
                    status == ConnectionStatus.ConnectionFailed ||
                    status == ConnectionStatus.Timeout ||
                    status == ConnectionStatus.ServerUnreachable)
                {
                    _lastErrorMessage = message;
                }
            }
        }

        /// <summary>
        /// 记录日志
        /// </summary>
        private void Log(string message)
        {
            if (_debugMode) Debug.Log($"[WebSocket] {message}");
        }

        /// <summary>
        /// 记录错误
        /// </summary>
        private void LogError(string message)
        {
            Debug.LogError($"[WebSocket] {message}");
        }

        #endregion

        #region WebSocket事件处理程序

        private void OnWebSocketOpenHandler()
        {
            _isConnected = true;
            SetConnectionState(ConnectionState.Connected);
            SetConnectionStatus(ConnectionStatus.Connected, "成功连接到服务器");

            // 重置重连计数器
            Log($"【重连管理】连接成功，重置重连次数: 0");
            _reconnectAttempts = 0;

            // 执行连接回调
            _onConnectCallback?.Invoke(true);
            _onConnectCallback = null;

            // 触发连接事件
            OnConnected?.Invoke();
        }

        private void OnWebSocketCloseHandler(WebSocketCloseCode closeCode)
        {
            bool wasConnected = _isConnected;
            _isConnected = false;
            SetConnectionState(ConnectionState.Disconnected);

            // 获取关闭代码和原因（NativeWebSocket库只提供closeCode）
            int code = (int)closeCode;
            string reason = closeCode.ToString();

            // 非正常关闭时重置重连参数
            if (_reconnectOnDisconnect && code != 1000) // 1000=正常关闭
            {
                Log($"【重连管理】检测到非正常关闭 (代码:{code})，设置重连次数: {_maxReconnectAttempts}");
                _reconnectAttempts = _maxReconnectAttempts;
                _reconnectTimer = 0f;
                SetConnectionStatus(ConnectionStatus.ConnectionFailed, $"连接异常关闭 (代码:{code}, 原因:{reason})");
            }
            else
            {
                Log($"【重连管理】正常关闭连接 (代码:{code})，不触发重连");
                SetConnectionStatus(ConnectionStatus.Disconnected, "连接已关闭");
            }

            // 如果之前是连接状态，才触发断开事件
            if (wasConnected)
            {
                // 触发断开连接事件
                OnDisconnected?.Invoke(code, reason);
            }
        }

        private void OnWebSocketErrorHandler(string errorMsg)
        {
            _lastErrorMessage = $"WebSocket错误: {errorMsg}";
            LogError($"{_lastErrorMessage}, url is {_serverUrl}");

            // 为特定的WebSocket升级错误提供更多诊断信息
            if (errorMsg.Contains("upgrade' token not found in 'Connection' header") ||
                errorMsg.Contains("the client is not using the websocket protocol") ||
                errorMsg.Contains("error during WebSocket handshake"))
            {
                LogError("WebSocket握手失败 - 无法进行协议升级。可能的原因:");
                LogError("1. 代理服务器(如Nginx)没有正确配置WebSocket头信息");
                LogError("2. 防火墙拦截或修改了WebSocket握手请求");
                LogError("3. 使用了不支持WebSocket的网络环境");
                LogError("4. 服务器可能将HTTP测试请求误认为WebSocket连接请求");
                LogError("解决方案:");
                LogError("1. 确保Nginx配置中包含: proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection \"upgrade\";");
                LogError("2. 检查网络环境和代理设置");
                LogError("3. 尝试直接连接到WebSocket服务器，绕过可能的代理");
                LogError("4. 检查服务器日志，确保服务器正确处理WebSocket握手");
            }

            SetConnectionStatus(ConnectionStatus.Error, _lastErrorMessage);
            OnError?.Invoke(errorMsg);
        }

        private void OnWebSocketMessageHandler(byte[] data)
        {
            try
            {
                // 检查消息大小
                if (data == null)
                {
                    LogError("收到空的WebSocket消息");
                    return;
                }

                // 记录消息接收信息
                if (_debugMode)
                {
                    Log($"收到WebSocket消息: {data.Length}字节");

                    // 记录前32字节用于调试
                    if (data.Length > 0)
                    {
                        string hexDump = BitConverter.ToString(data, 0, Math.Min(32, data.Length)).Replace("-", " ");
                        Log($"消息内容(前32字节): {hexDump}");
                    }
                }

                // 直接触发二进制消息事件，让WebSocketMessageHandler进行二进制处理
                OnBinaryMessageReceived?.Invoke(data);

                // 将消息加入队列，仅作为二进制处理
                _messageQueue.Enqueue(new WebSocketMessage(data));
            }
            catch (Exception ex)
            {
                LogError($"处理WebSocket消息异常: {ex.Message}");
                // 异常情况下尝试将消息作为二进制入队
                try
                {
                    _messageQueue.Enqueue(new WebSocketMessage(data));
                }
                catch { }
            }
        }

        private void UnregisterWebSocketEvents()
        {
            if (_webSocket != null)
            {
                _webSocket.OnOpen -= OnWebSocketOpenHandler;
                _webSocket.OnClose -= OnWebSocketCloseHandler;
                _webSocket.OnError -= OnWebSocketErrorHandler;
                _webSocket.OnMessage -= OnWebSocketMessageHandler;
            }
        }

        private void Emit<T>(T data) where T : EventArgs
        {
            EventManager.Instance.RaiseEvent<T>(this, data);
        }

        #endregion

        #region 辅助类

        /// <summary>
        /// WebSocket消息类型
        /// </summary>
        private class WebSocketMessage
        {
            public string Text { get; }
            public byte[] Binary { get; }
            public bool IsText { get; }

            public WebSocketMessage(string text)
            {
                Text = text;
                IsText = true;
            }

            public WebSocketMessage(byte[] binary)
            {
                Binary = binary;
                IsText = false;
            }
        }

        #endregion
    }
}